package com.cn.coder;

import com.cn.common.RemoteCommand;
import com.cn.msg.Message;
import com.cn.msg.ProxyMessage;
import com.cn.util.SerializationUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;

import java.nio.ByteBuffer;

/**
 * 消息解码器
 */
public class MessageDecoder extends LengthFieldBasedFrameDecoder {

    //判断传送客户端传送过来的数据是否按照协议传输，头部信息的大小应该是 byte+byte+int = 1+1+4 = 6
    private static final int HEADER_SIZE = 6;

    private static int maxFrameLength = 16777216;//数据大小， 2K
    private static int lengthFieldLength = 4;//数据长度
    private static int lengthFieldOffset = 11;//length的起始位置(byte + byte + byte + long)
    private static int lengthAdjustment = 0;
    private static int initialBytesToStrip = 0;//

    public MessageDecoder() {
        super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip);
    }

    /**
     * @param maxFrameLength      解码时，处理每个帧数据的最大长度
     * @param lengthFieldOffset   该帧数据中，存放该帧数据的长度的数据的起始位置
     * @param lengthFieldLength   记录该帧数据长度的字段本身的长度
     * @param lengthAdjustment    修改帧数据长度字段中定义的值，可以为负数
     * @param initialBytesToStrip 解析的时候需要跳过的字节数
     * @param failFast            为true，当frame长度超过maxFrameLength时立即报TooLongFrameException异常，为false，读取完整个帧再报异常
     */
    public MessageDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) {
        super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        ByteBuf frame = null;
        try {
            frame = (ByteBuf) super.decode(ctx, in);
            if (frame == null) {
                return null;
            }

            ByteBuffer readBuffer = frame.nioBuffer();
            byte type = readBuffer.get();
            byte flag = readBuffer.get();
            byte requestWrapper = readBuffer.get();
            long opaque = readBuffer.getLong();
            int length = readBuffer.getInt();

            Message msg = new Message();
            msg.setType(type);
            msg.setFlag(flag);
            msg.setLength(length);
            msg.setNettyRequestWrapperCode(requestWrapper);
            msg.setOpaque(opaque);

            if (length > 0) {

                byte[] data = new byte[length];
                readBuffer.get(data);
                msg.setByteBodys(data);
            }
            return msg;
        } catch (Exception e) {
//            e.printStackTrace();
            System.out.println("编码异常：" + this.getClass().getSimpleName());
            ctx.close();
        } finally {
            if (frame != null) {
                frame.release();
            }
        }
        return null;
    }
}
